package com.example.myapplication.picUtils

import android.Manifest
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.provider.OpenableColumns
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.util.UUID

interface ImagePickerCallback {


    fun onImagesSelected(originalUris: List<Uri>, compressedFiles: List<File>?)
    fun onError(exception: Exception)
    fun onPermissionDenied(deniedPermissions: List<String>)
}

class ImagePicker private constructor(
    private val activityOrFragment: Any, // ComponentActivity or Fragment
    private val callback: ImagePickerCallback
) {

    private val context: Context = when (activityOrFragment) {
        is ComponentActivity -> activityOrFragment
        is Fragment -> activityOrFragment.requireContext()
        else -> throw IllegalArgumentException("Must be initialized with ComponentActivity or Fragment")
    }

    private val coroutineScope = CoroutineScope(Dispatchers.Main + Job()) // UI 相关的用 Main，IO 用 IO

    private var pickMediaLauncher: ActivityResultLauncher<PickVisualMediaRequest>? = null
    private var pickMultipleMediaLauncher: ActivityResultLauncher<PickVisualMediaRequest>? = null
    private var requestPermissionLauncher: ActivityResultLauncher<Array<String>>? = null

    private var allowMultiple: Boolean = false
    private var maxSelectionCount: Int = 5 // 默认最多5张
    private var enableCompression: Boolean = true
    private var compressionQuality: Int = 80 // 0-100
    private var compressionWidth: Int = 1080 // 压缩后的目标宽度，可根据需求调整
    private var compressionHeight: Int = 1920 // 压缩后的目标高度
    private var targetDirectory: File = context.cacheDir // 默认压缩到缓存目录

    init {
        setupLaunchers()
    }

    private fun setupLaunchers() {
        val registryOwner = when (activityOrFragment) {
            is ComponentActivity -> activityOrFragment
            is Fragment -> activityOrFragment
            else -> throw IllegalArgumentException("Invalid owner for ActivityResultLaunchers")
        }

        pickMediaLauncher = registryOwner.registerForActivityResult(
            ActivityResultContracts.PickVisualMedia()
        ) { uri ->
            handleImageUris(uri?.let { listOf(it) } ?: emptyList())
        }

        pickMultipleMediaLauncher = registryOwner.registerForActivityResult(
            ActivityResultContracts.PickMultipleVisualMedia(maxSelectionCount.coerceAtLeast(1))
        ) { uris ->
            handleImageUris(uris)
        }

        requestPermissionLauncher = registryOwner.registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) { permissions ->
            val grantedPermissions = permissions.filter { it.value }.keys.toList()
            val deniedPermissions = permissions.filterNot { it.value }.keys.toList()

            if (deniedPermissions.isEmpty()) {
                launchActualPicker()
            } else {
                Log.w(TAG, "Permissions denied: $deniedPermissions")
                callback.onPermissionDenied(deniedPermissions)
            }
        }
    }

    private fun handleImageUris(uris: List<Uri>) {
        if (uris.isNotEmpty()) {
            Log.d(TAG, "Number of items selected: ${uris.size}")
            if (enableCompression) {
                coroutineScope.launch {
                    try {
                        val compressedFiles = uris.mapNotNull { uri ->
                            compressImage(uri)
                        }
                        callback.onImagesSelected(uris, compressedFiles)
                    } catch (e: Exception) {
                        Log.e(TAG, "Error during compression", e)
                        callback.onError(e)
                    }
                }
            } else {
                callback.onImagesSelected(uris, null)
            }
        } else {
            Log.d(TAG, "No media selected")
            // 可以选择在这里也回调一个空列表或特定状态
        }
    }

    private suspend fun compressImage(uri: Uri): File? = withContext(Dispatchers.IO) {
        try {
            val inputStream =
                context.contentResolver.openInputStream(uri) ?: return@withContext null
            val originalBitmap = BitmapFactory.decodeStream(inputStream)
            inputStream.close()

            // 计算采样率以避免 OOM，并初步缩放
            val options = BitmapFactory.Options().apply {
                inJustDecodeBounds = true // 只获取图片大小，不加载到内存
            }
            context.contentResolver.openInputStream(uri)
                ?.use { BitmapFactory.decodeStream(it, null, options) }

            options.inSampleSize =
                calculateInSampleSize(options, compressionWidth, compressionHeight)
            options.inJustDecodeBounds = false // 实际加载 Bitmap

            val scaledBitmap = context.contentResolver.openInputStream(uri)
                ?.use { BitmapFactory.decodeStream(it, null, options) }
                ?: return@withContext null

            // 创建输出文件
            val outputFileName =
                "IMG_CMP_${UUID.randomUUID()}_${getFileNameFromUri(context, uri, "compressed.jpg")}"
            val outputFile = File(targetDirectory, outputFileName)
            if (!targetDirectory.exists()) {
                targetDirectory.mkdirs()
            }

            FileOutputStream(outputFile).use { fos ->
                // 根据文件扩展名选择压缩格式，这里简化为 JPEG
                scaledBitmap.compress(Bitmap.CompressFormat.JPEG, compressionQuality, fos)
            }
            scaledBitmap.recycle() // 及时回收 Bitmap
            Log.d(TAG, "Image compressed: ${outputFile.absolutePath}")
            return@withContext outputFile
        } catch (e: Exception) {
            Log.e(TAG, "Failed to compress image: $uri", e)
            return@withContext null
        }
    }

    // 计算 BitmapFactory.Options.inSampleSize 的辅助函数
    private fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int,
        reqHeight: Int
    ): Int {
        val (height: Int, width: Int) = options.run { outHeight to outWidth }
        var inSampleSize = 1

        if (height > reqHeight || width > reqWidth) {
            val halfHeight: Int = height / 2
            val halfWidth: Int = width / 2
            while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
                inSampleSize *= 2
            }
        }
        return inSampleSize
    }


    public fun launchPicker() {
        val neededPermissions = mutableListOf<String>()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13+
            neededPermissions.add(Manifest.permission.READ_MEDIA_IMAGES)
            // 如果还需要视频，可以添加 Manifest.permission.READ_MEDIA_VIDEO
        } else {
            neededPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE)
            // 如果需要写入（例如保存到公共目录，虽然不推荐），则添加 WRITE_EXTERNAL_STORAGE，但要注意分区存储
        }
        // 如果您的库还支持拍照，则添加相机权限
        // neededPermissions.add(Manifest.permission.CAMERA)

        val currentGrantedPermissions = neededPermissions.filter {
            context.checkSelfPermission(it) == android.content.pm.PackageManager.PERMISSION_GRANTED
        }
        val permissionsToRequest =
            neededPermissions.filterNot { currentGrantedPermissions.contains(it) }.toTypedArray()

        if (permissionsToRequest.isEmpty()) {
            launchActualPicker()
        } else {
            requestPermissionLauncher?.launch(permissionsToRequest)
        }
    }

    private fun launchActualPicker() {
        if (allowMultiple) {
            pickMultipleMediaLauncher?.launch(
                PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) // 或者 ImageAndVideo
            )
        } else {
            pickMediaLauncher?.launch(
                PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) // 或者 ImageAndVideo
            )
        }
    }

    companion object {
        private const val TAG = "ImagePickerLib"

        fun with(activity: ComponentActivity, callback: ImagePickerCallback): Builder {
            return Builder(activity, callback)
        }

        fun with(fragment: Fragment, callback: ImagePickerCallback): Builder {
            return Builder(fragment, callback)
        }

        // 从URI获取文件名
        fun getFileNameFromUri(
            context: Context,
            uri: Uri,
            defaultName: String = "unknown_file"
        ): String {
            var fileName = defaultName
            try {
                context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
                    if (cursor.moveToFirst()) {
                        val displayNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                        if (displayNameIndex != -1) {
                            fileName = cursor.getString(displayNameIndex)
                        }
                    }
                }
            } catch (e: Exception) {
                Log.e(TAG, "Error getting file name from URI", e)
            }
            return fileName
        }
    }

    class Builder(
        private val activityOrFragment: Any,
        private val callback: ImagePickerCallback
    ) {
        private var allowMultiple: Boolean = false
        private var maxSelectionCount: Int = 5
        private var enableCompression: Boolean = true
        private var compressionQuality: Int = 80
        private var compressionWidth: Int = 1080
        private var compressionHeight: Int = 1920
        private var targetDirectory: File? = null

        fun allowMultiple(allow: Boolean = true, maxCount: Int = 5): Builder {
            this.allowMultiple = allow
            this.maxSelectionCount = if (allow) maxCount.coerceAtLeast(1) else 1
            return this
        }

        fun enableCompression(enable: Boolean = true): Builder {
            this.enableCompression = enable
            return this
        }

        fun compressionQuality(quality: Int): Builder {
            this.compressionQuality = quality.coerceIn(0, 100)
            return this
        }

        fun compressionDimensions(width: Int, height: Int): Builder {
            this.compressionWidth = width
            this.compressionHeight = height
            return this
        }

        fun targetDirectory(directory: File): Builder {
            this.targetDirectory = directory
            return this
        }

        fun build(): ImagePicker {
            val picker = ImagePicker(activityOrFragment, callback)
            picker.allowMultiple = this.allowMultiple
            picker.maxSelectionCount = this.maxSelectionCount
            picker.enableCompression = this.enableCompression
            picker.compressionQuality = this.compressionQuality
            picker.compressionWidth = this.compressionWidth
            picker.compressionHeight = this.compressionHeight
            this.targetDirectory?.let { picker.targetDirectory = it }
            return picker
        }

        fun pick() { // 直接调用 pick 方法
            build().launchPicker()
        }
    }
}
